home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / macabuse / imlib / readxwd.c < prev    next >
C/C++ Source or Header  |  1997-05-20  |  19KB  |  655 lines

  1. #include "image.hpp"
  2. #include "palette.hpp"
  3. #define MAXCOLORS 256
  4. //#define MC(x) (((x)<3)==0)
  5. #define MC(x) (x!=0)
  6.  
  7. // the following table converts rgb to cym.
  8. int ca[8]={1,1,1,1,0,0,0,0},
  9.     ma[8]={1,0,1,0,1,0,1,0},
  10.     ya[8]={1,1,0,0,1,1,0,0};
  11. // the following defines make a color threshold
  12. #define RGB2C(r,g,b) (char)(ca[MC(b)|MC(g)<<1|MC(r)<<2])
  13. #define RGB2Y(r,g,b) (char)(ya[MC(b)|MC(g)<<1|MC(r)<<2])
  14. #define RGB2M(r,g,b) (char)(ma[MC(b)|MC(g)<<1|MC(r)<<2])
  15.  
  16. #define LSBFirst    0
  17. #define MSBFirst    1
  18.  
  19. #define XYBitmap    0
  20. #define XYPixmap    1
  21. #define ZPixmap        2
  22.  
  23. #define StaticGray    0
  24. #define GrayScale    1
  25. #define StaticColor    2
  26. #define PseudoColor    3
  27. #define TrueColor    4
  28. #define DirectColor    5
  29.  
  30. typedef unsigned long xwdval;
  31. #define X11WD_FILE_VERSION 7
  32. typedef struct {
  33.     xwdval header_size;        /* Size of the entire file header (bytes). */
  34.     xwdval file_version;    /* X11WD_FILE_VERSION */
  35.     xwdval pixmap_format;    /* Pixmap format */
  36.     xwdval pixmap_depth;    /* Pixmap depth */
  37.     xwdval pixmap_width;    /* Pixmap width */
  38.     xwdval pixmap_height;    /* Pixmap height */
  39.     xwdval xoffset;        /* Bitmap x offset */
  40.     xwdval byte_order;        /* MSBFirst, LSBFirst */
  41.     xwdval bitmap_unit;        /* Bitmap unit */
  42.     xwdval bitmap_bit_order;    /* MSBFirst, LSBFirst */
  43.     xwdval bitmap_pad;        /* Bitmap scanline pad */
  44.     xwdval bits_per_pixel;    /* Bits per pixel */
  45.     xwdval bytes_per_line;    /* Bytes per scanline */
  46.     xwdval visual_class;    /* Class of colormap */
  47.     xwdval red_mask;        /* Z red mask */
  48.     xwdval green_mask;        /* Z green mask */
  49.     xwdval blue_mask;        /* Z blue mask */
  50.     xwdval bits_per_rgb;    /* Log base 2 of distinct color values */
  51.     xwdval colormap_entries;    /* Number of entries in colormap */
  52.     xwdval ncolors;        /* Number of Color structures */
  53.     xwdval window_width;    /* Window width */
  54.     xwdval window_height;    /* Window height */
  55.     long window_x;        /* Window upper left X coordinate */
  56.     long window_y;        /* Window upper left Y coordinate */
  57.     xwdval window_bdrwidth;    /* Window border width */
  58.     } X11WDFileHeader;
  59.  
  60. typedef struct {
  61.     unsigned long pixel;
  62.     unsigned short red, green, blue;
  63.     char flags;            /* do_red, do_green, do_blue */
  64.     char pad;
  65.     } X11XColor;
  66.  
  67. image *getinit(FILE *file, palette *&pal, int *padrightP);
  68. void getimage(FILE *file,image *image, int pad);
  69. int getpixnum(FILE *file);
  70.  
  71.  
  72. HBITMAP readxwd(char *input_file,palette *&pal)
  73. //char *hdfpal,int *palsize,int *cols,int *rows)
  74. {
  75.   FILE *ifd;
  76.   char *imageP;
  77.   unsigned int nspace;
  78.   int padright;
  79.   HBITMAP im;
  80.  
  81.   /* open input file */
  82.   if (strcmp(input_file,"-") == 0)
  83.     ifd = stdin;d)
  84.   { printf("Unable to open %s\n"
  85.        "Get your story right and try again.\n",input_file);
  86.     exit(0);
  87.   }
  88.   printf("Reading image\n");
  89.   im=getinit( ifd, pal, &padright, int &xres, int &yres);
  90. //cols, rows, &padright, palsize, hdfpal);
  91.  
  92.   /* alloc image array */
  93.  
  94.   /* fill image array */
  95.   getimage(ifd, im, padright);
  96.  
  97.   return(im);
  98. }
  99.  
  100. int bits_per_item, bits_used, bit_shift, bits_per_pixel, pixel_mask;
  101. int bit_order, byte_swap;
  102. char buf[4];
  103. char *byteP;
  104. short *shortP;
  105. long *longP;
  106.  
  107.  
  108. int bs_int(int s);
  109. long bs_long(long s);
  110. short bs_short(short s );
  111.  
  112.  
  113. HBITMAP getinit(FILE *file, palette *&pal, int *padrightP, int &xres, int &yres);)
  114. {
  115.   /* Assume X11 headers are larger than X10 ones. */
  116.   unsigned char header[sizeof(X11WDFileHeader)];
  117.   image *im;
  118.   X11WDFileHeader *h11P;
  119.   char junk[800];
  120.   int i, np, dummy1, dummy2, dummy3;
  121.   unsigned  short minred, maxred;
  122.   X11XColor x11col;
  123.  
  124.   h11P = (X11WDFileHeader *) header;
  125.  
  126.   if (fread(header,sizeof(*h11P),1,file) != 1 )
  127.     {
  128.       fprintf(stderr,"couldn't read X11 XWD file header");
  129.       exit(-1);
  130.     }
  131.   if ( h11P->file_version != X11WD_FILE_VERSION )
  132.     {
  133.       byte_swap = 1;
  134.       h11P->header_size = bltl(h11P->header_size);
  135.       h11P->file_version = bltl(h11P->file_version);
  136.       h11P->pixmap_format = bltl(h11P->pixmap_format);
  137.       h11P->pixmap_depth = bltl(h11P->pixmap_depth);
  138.       h11P->pixmap_width = bltl(h11P->pixmap_width);
  139.       h11P->pixmap_height = bltl(h11P->pixmap_height);
  140.       h11P->xoffset =  bltl(h11P->xoffset);
  141.       h11P->byte_order =  bltl(h11P->byte_order);
  142.       h11P->bitmap_unit = bltl(h11P->bitmap_unit);
  143.       h11P->bitmap_bit_order = bltl(h11P->bitmap_bit_order);
  144.       h11P->bitmap_pad = bltl(h11P->bitmap_pad);
  145.       h11P->bits_per_pixel = bltl(h11P->bits_per_pixel);
  146.       h11P->bytes_per_line = bltl(h11P->bytes_per_line);
  147.       h11P->visual_class = bltl(h11P->visual_class);
  148.       h11P->red_mask = bltl(h11P->red_mask);
  149.       h11P->green_mask = bltl(h11P->green_mask);
  150.       h11P->blue_mask = bltl(h11P->blue_mask);
  151.       h11P->bits_per_rgb = bltl(h11P->bits_per_rgb);
  152.       h11P->colormap_entries = bltl(h11P->colormap_entries);
  153.       h11P->ncolors = bltl(h11P->ncolors);
  154.       h11P->window_width = bltl(h11P->window_width);
  155.       h11P->window_height = bltl(h11P->window_height);
  156.       h11P->window_x = bltl(h11P->window_x);
  157.       h11P->window_y = bltl(h11P->window_y);
  158.       h11P->window_bdrwidth = bltl(h11P->window_bdrwidth);
  159.     }
  160.  
  161.   if ( fread( junk, 1, h11P->header_size - sizeof(*h11P), file ) !=
  162.       h11P->header_size - sizeof(*h11P) )
  163.     {
  164.       fprintf(stderr,"couldn't read rest of X11 XWD file header");
  165.       exit(-1);
  166.     }
  167.  
  168.   /* Check whether we can handle this dump. */
  169.   if ( h11P->pixmap_depth > 8 )
  170.     {
  171.       fprintf(stderr,"can't handle X11 pixmap_depth > 8");
  172.       exit(-1);
  173.     }
  174.   if ( h11P->bits_per_rgb > 8 )
  175.     {
  176.       fprintf(stderr,"can't handle X11 bits_per_rgb > 8");
  177.       exit(-1);
  178.     }
  179.   if ( h11P->ncolors > MAXCOLORS )
  180.     {
  181.       fprintf(stderr,"can't handle X11 ncolors > %d");
  182.       exit(-1);
  183.     }
  184.   if ( h11P->pixmap_format != ZPixmap )
  185.     {
  186.       fprintf(stderr,"can't handle X11 pixmap_format %d", h11P->pixmap_format,
  187.           0,0,0,0 );
  188.       exit(-1);
  189.     }
  190.   if ( h11P->bitmap_unit != 8 && h11P->bitmap_unit != 16 &&
  191.       h11P->bitmap_unit != 32 )
  192.     {
  193.       fprintf(stderr,"X11 bitmap_unit (%d) is non-standard - can't handle");
  194.       exit(-1);
  195.     }
  196.   xres=h11P->pixmap_width;
  197.   yres=h11P->pixmap_height;
  198.   im=new image(h11P->pixmap_width,h11P->pixmap_height);
  199.   pal=new palette(h11P->colormap_entries);
  200.   *padrightP = h11P->bytes_per_line * 8 / h11P->bits_per_pixel - im->width();
  201.  
  202. /*****************************************************************************/
  203.   /* Read X11 colormap. */
  204. minred = 65535;
  205. maxred = 0;
  206.   for ( i = 0; i < h11P->colormap_entries; i++ )
  207.     {
  208.       if ( fread( &x11col, sizeof(X11XColor), 1, file ) != 1 )
  209.     {
  210.       fprintf(stderr,"couldn't read X11 XWD colormap");
  211.       exit(-1);
  212.     }
  213.     else
  214.     {
  215.       x11col.pixel=bltl(x11col.pixel);
  216.       x11col.red=bstl(x11col.red);
  217.       x11col.green=bstl(x11col.green);
  218.       x11col.blue=bstl(x11col.blue);
  219.     }
  220.       if (x11col.pixel < 256)
  221.     {
  222.       if (minred > x11col.red) minred = x11col.red;
  223.       if (maxred < x11col.red) maxred = x11col.red;
  224.       dummy1 = (unsigned) x11col.red / 256 ;
  225.       dummy2 = (unsigned) x11col.green / 256 ;
  226.       dummy3 = (unsigned) x11col.blue / 256 ;
  227.       pal->set(i,dummy1,dummy2,dummy3);
  228.     }
  229.       else
  230.     {
  231.       fprintf(stderr,"pixel value outside of valid HDF palette\n");
  232.       exit(-1);
  233.     }
  234.     }
  235.   /* rest of stuff for getpixnum */
  236.   bits_per_item = h11P->bitmap_unit;
  237.   bits_used = bits_per_item;
  238.   bits_per_pixel = h11P->bits_per_pixel;
  239.   bit_order = h11P->bitmap_bit_order;
  240.   pixel_mask = ( 1 << bits_per_pixel ) - 1;
  241.  
  242.   byteP = (char *) buf;
  243.   shortP = (short *) buf;
  244.   longP = (long *) buf;
  245.   return im;
  246. }
  247.  
  248. void getimage(FILE *file,HBITMAP &im.int pad)
  249. {
  250.   int i,j;
  251.   unsigned char *sl;
  252.   for (i=0; i<im->height(); i++)
  253.     {
  254.       if (i%50==0)
  255.     printf("Line %d of %d\n",i+1,im->height());
  256.       sl=im->scan_line(i);
  257.       for (j=0; j<im->width(); j++)
  258.     sl[j]= getpixnum(file);
  259.  
  260.       for ( j = 0; j < pad; j++ )
  261.     getpixnum( file );
  262.     }
  263. }
  264.  
  265.  
  266. int getpixnum(FILE *file)
  267. {
  268.   int p;
  269.  
  270.   if ( bits_used == bits_per_item )
  271.     {
  272.       if ( fread( buf, bits_per_item / 8, 1, file ) != 1 )
  273.     fprintf(stderr, "couldn't read bits" );
  274.       if ( byte_swap )
  275.     switch ( bits_per_item )
  276.       {
  277.       case 8:
  278.         break;
  279.  
  280.       case 16:
  281.         *shortP = bstl(*shortP) ;
  282.         break;
  283.  
  284.       case 32:
  285.         *longP = bltl(*longP) ;
  286.         break;
  287.  
  288.       default:
  289.         fprintf(stderr, "can't happen" );
  290.       }
  291.       bits_used = 0;
  292.  
  293. //      if ( bit_order == MSBFirst )
  294.     bit_shift = bits_per_item - bits_per_pixel;
  295. //      else
  296. //    bit_shift = 0;
  297.     }
  298.  
  299.   switch ( bits_per_item )
  300.     {
  301.     case 8:
  302.       p = ( *byteP >> bit_shift) & pixel_mask;
  303.       break;
  304.  
  305.     case 16:
  306.       p = ( *shortP >> bit_shift) & pixel_mask;
  307.       break;
  308.  
  309.     case 32:
  310.       p = ( *longP >> bit_shift) & pixel_mask;
  311.       break;
  312.  
  313.     default:
  314.       fprintf(stderr, "can't happen" );
  315.     }
  316.  
  317. //  if ( bit_order == MSBFirst )
  318.     bit_shift -= bits_per_pixel;
  319. //  else
  320. //    bit_shift += bits_per_pixel;
  321.   bits_used += bits_per_pixel;
  322.  
  323.   return p;
  324. }
  325.  
  326.  
  327. short bs_short(short s )
  328. {
  329.   short ss;
  330.   unsigned char *bp, t;
  331.  
  332.   ss = s;
  333.   bp = (unsigned char *) &ss;
  334.   t = bp[0];
  335.   bp[0] = bp[1];
  336.   bp[1] = t;
  337.   return ss;
  338. }
  339.  
  340. int bs_int(int i )
  341. {
  342.   int ii;
  343.   unsigned char *bp, t;
  344.  
  345.   ii = i;
  346.   bp = (unsigned char *) ⅈ
  347.   t = bp[0];
  348.   bp[0] = bp[3];
  349.   bp[3] = t;
  350.   t = bp[1];
  351.   bp[1] = bp[2];
  352.   bp[2] = t;
  353.   return ii;
  354. }
  355.  
  356. long bs_long(long l )
  357. {
  358.   return bs_int( l );
  359. }
  360.  
  361. struct BMP_header
  362. {
  363.   char id[2];
  364.   long filesize;
  365.   int reserved[2];
  366.   long headersize,infosize,width,height;
  367.   int biplanes,bits;
  368.   long bicompression, bisizeimage, bixpelspermeter, biypelspermeter,
  369.        biclrused,biclrimportant;
  370. } bmp;
  371.  
  372. void write_bmp(image *im, palette *pal, char *filename)
  373. {
  374.   FILE *fp;
  375.   int i,bytes;
  376.   unsigned char pal_quad[4];
  377. //  fp=fopen("d:\\windows\\256color.bmp","rb");
  378. //  fread(&bmp,1,sizeof(bmp),fp);
  379. //  fclose(fp);
  380.   fp=fopen(filename,"wb");
  381.   if (!fp)
  382.   { printf("Error : unable to open %s for writing!\n");
  383.     exit(0);
  384.   }
  385.   bytes=(im->width()+3)/4;
  386.   memset((char *)&bmp,0,sizeof(bmp));
  387.   memcpy(bmp.id,"BM",2);
  388.   bmp.width=im->width();
  389.   bmp.height=im->height();
  390.   bmp.bits=8;
  391.   bmp.infosize=0x28L;
  392.   bmp.biplanes=1;
  393.   bmp.headersize=1078;
  394.   bmp.filesize=bmp.headersize+bytes*im->height()*4;
  395.   bmp.bisizeimage=im->width()*im->height();
  396.   bmp.biclrused=256;
  397.   bmp.biclrimportant=256;
  398.   fwrite(&bmp,1,sizeof(bmp),fp);
  399.   pal_quad[3]=0;
  400.   for (i=0;i<256;i++)
  401.   {
  402.     pal->get(i,pal_quad[2],pal_quad[1],pal_quad[0]);
  403.     fwrite(pal_quad,1,4,fp);
  404.   }
  405.   for (i=im->height();i;i--)
  406.     fwrite(im->scan_line(i-1),1,bytes*4,fp);
  407.   fclose(fp);
  408. }
  409.  
  410. image *image24(image *im, palette *pal, int rev)
  411. {
  412.   image *ni;
  413.   unsigned char *sl1,*sl2;
  414.   int i,x;
  415.   unsigned char r,g,b;
  416.   printf("Creating image size (%d, %d)\n",im->width()*3,im->height());
  417.   ni=new image(im->width()*3,im->height());
  418.   printf("Image created\n");
  419.   for (i=0;i<im->height();i++)
  420.   {
  421.     if (i%50==0)
  422.       printf("Line %d of %d\n",i+1,im->height());
  423.  
  424.     sl1=   sl2[x*3]=r; sl2[x*3+1]=g; sl2[x*3+2]=b;
  425.     }
  426.     im->set_page_swapable();
  427.   }
  428.   return ni;
  429. }
  430.  
  431. unsigned char addb(int n1, int n2)
  432. { int n3;
  433.   n3=n1+n2;
  434.   return n3>255 ? 255 : (n3<0 ? 0 : n3);
  435. }
  436.  
  437. // this function takes an image min 8 bit format, converts it to 24 bit
  438. // color and dithers it so that it can be printed on an deskjet
  439. /// (i.e it reduces it down to 8 colors)
  440. image *color_dither(image *im, palette *pal, int rev)
  441. {
  442.   image *i24;
  443.   unsigned char min[3],max[3],mid[3],*ad,*sl,*sl2,crimp;
  444.   int i,j,x,y,delta;
  445.   (void *)ad=pal->addr();
  446.  
  447.   // find the minimum and maximum  red green and blue in the image
  448.   memset(min,0xff,3); memset(max,0,3);
  449.   for (j=0;j<3;j++,ad++)
  450.     for (y=0;y<im->height();y++)
  451.     { sl2=im->scan_line(y);
  452.       for (x=0;x<im->width();x++)
  453.       {
  454.     if (ad[sl2[x]*3]<min[j]) min[j]=ad[i*3];
  455.     if (ad[sl2[x]*3]>max[j]) max[j]=ad[i*3];
  456.       }
  457.     }
  458.   // find the middle color used for red green and blue
  459.   for (i=0;i<3;i++)
  460.     mid[i]=(int)((int)max[i]+(int)min[i])/2;
  461.   // convert the image to 24 bit color.
  462.   printf("Converting to 24 bit color...\n");
  463.   i24=image24(im,pal,rev);
  464.   printf("Dithering using flyod stienberg algorithm\n");
  465.   for (y=0;y<im->height();y++)
  466.   { if (y%20==0)
  467.       printf("Line %d of %d\n",y+1,im->height());
  468.     sl=i24->scan_line(y);
  469.     i24->set_page_unswapable();
  470.  
  471.     if (y+1<im->height())
  472.       sl2=i24->scan_line(y+1);  // get the scan line below this one
  473.     for (x=0;x<im->width();x++)
  474.     {
  475.       // diffuse the colors using flyod stienburg dithering algorithm
  476.       for (j=0;j<3;j++)
  477.       {
  478.     crimp = sl[x*3+j]>mid[j] ? 255 : 0;
  479.     delta=sl[x*3+j]-crimp;
  480.     sl[x*3+j]=crimp;
  481.     if (x+1<im->width())
  482.     { sl[(x+1)*3+j]=addb(sl[(x+1)*3+j],delta*7/16);
  483.       if (y+1<im->height())
  484.         sl2[(x+1)*3+j]=addb(sl2[(x+1)*3+j],delta*1/16);
  485.     }
  486.     if (y+1<im->height())
  487.     { if (x>0)
  488.         sl2[(x-1)*3+j]=addb(sl2[(x-1)*3+j],delta*3/16);
  489.       sl2[(x)*3+j]=addb(sl2[(x)*3+j],delta*5/16);
  490.     }
  491.       }
  492.     }
  493.     sl=i24->scan_line(y);
  494.     i24->set_page_swapable();
  495.  
  496.   }
  497.   return i24;
  498. }
  499.  
  500. image *rotate90(image *im)
  501. {
  502.   image *i;
  503.   int x,y,w,h;
  504.   w=im->width();
  505.   h=im->height();
  506.   printf("Rotating image 90 deg\n");
  507.   i=new image(im->height(),im->width());
  508.   for (x=0;x<w;x++)
  509.   {
  510.     if (x%20==0)
  511.       printf("Row %d of %d\n",x,im->width());
  512.     for (y=0;y<h;y++)
  513.       i->putpixel(y,w-x-1,im->pixel(x,y));
  514.   }
  515.   return i;
  516. }
  517.  
  518. void deskjet_print(int argc, char **argv)
  519. {
  520.   int i,dpi=100;
  521.   int y,x,byteo,bito,outc,outy,outm,outcv, outyv,outmv, w,rev,inten,val,
  522.       display=0,bad=0,bmp=0,land=0,ch,xo=0,yo=0;
  523.   image *im,*i24;
  524.   palette *pal;
  525.   unsigned char *sl;
  526.   FILE *fp;
  527.   char def_name[10],*dev_name,*fname=NULL;
  528.   unsigned char cp[500],mp[500],yp[500],kp[500];
  529.   strcpy(def_name,"\\dev\\lp");  // set the default output device to /dev/lp
  530.         // since we are in vpix, however we will use the backslash
  531.   dev_name=def_name; rev=0;
  532.   for (i=1;i<argc;i++)
  533.     if (!strcmp(argv[i],"-dpi"))
  534.     { i++; dpi=atoi(argv[i]);
  535.       if (dpi!=75 && dpi!=100 && dpi!=150 && dpi!=300) bad=1; }
  536.     else if (!strcmp(argv[i],"-dev"))
  537.     { i++; dev_name=argv[i]; }
  538.     else if (!strcmp(argv[i],"-rev"))
  539.     { rev=1; }
  540.     else if (!strcmp(argv[i],"-land"))
  541.     { land=1; }
  542.     else if (!strcmp(argv[i],"-2bmp"))
  543.     { bmp=1; }
  544.     else if (!strcmp(argv[i],"-display"))
  545.     { display=1; }
  546.     else fname=argv[i];
  547.  
  548.   if (!fname || bad)
  549.   { printf("usage : %s [-dev device] [-dpi 75,100,150,300]\n"
  550.        "     [-rev] [-display] [-2bmp] [-land] filename\n\n"
  551.        "  default dpi is 100 (possible are 75/100/150/300)\n"
  552.        "  default printer is /dev/lp\n"
  553.        "  -rev, reverse black and white on the print out\n"
  554.        "  -display only displays the image to the screen and does not print it\n"
  555.        "    all ither options will be ignored\n"
  556.        "  -2bmp converts the image X window dump to a MicroSoft Windows bitmap (BMP)\n"
  557.        "    the file written to must be specified by -dev [filename]\n"
  558.        "    all other options will be ignored\n"
  559.        "  -land prints the image in landscape mode (sideways)\n"
  560.        "  filename is the name of the dump created by xwd\n"
  561.        "  Using Dos, the command [%s -dev lpt1] should be used\n",argv[0],argv[0]);
  562.     exit(0);
  563.   }
  564.   im=readxwd(fname,pal);
  565.   if (!im || !pal)
  566.   { printf("failed to read the image or the palette!\n");
  567.     exit(0);
  568.   }
  569.   if (display)
  570.   {
  571.     set_mode(19,argc,argv);
  572.     pal->load();                         // set the palette for the image we are going to print
  573.     im->put_image(screen,0,0);          // put the image on thge s÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷<0) yo+=10; break;
  574.       }
  575.     } while (ch!=' ' && ch!='q' && ch!=13);
  576.     close_graphics();
  577.   }
  578.   else if (bmp)
  579.     write_bmp(im,pal,dev_name);
  580.   else
  581.   {
  582.     fp=fopen(dev_name,"wb");  // open the output device for printing
  583.     if (!fp)
  584.     { printf("Unable to open %s for writing, make sure the path exsist and you\n"
  585.          "have write permission to the file\n",dev_name);
  586.       exit(0);
  587.     }
  588.     if (land)
  589.       im=rotate90(im);
  590.  
  591.     w=im->width()+7; w/=8; w*=8;
  592.     fprintf(fp,"E"           // reset the printer
  593.            "&l%dO"      // portrait/landscape mode
  594.            "*rbC"        // reset graphics
  595.            "*t%dR"        // set the resolution
  596.            "*r%dS"       // set the image width
  597.            "*r1A"        // start raster graphics at left edge
  598.            "*r-4U"         // set to CYM mode
  599.            ,land,dpi,w);
  600.   // now loop through all the scan lines of the image and pcik out the planes
  601.   // we need
  602.     i24=color_dither(im,pal,rev);
  603.     rev=0;  // turn off the revser option because the conversion to 24 bit takes care of it
  604.     printf("Printing...");
  605.     for (y=0;y<im->height();y++)
  606.     {
  607.       if (y%20==0)
  608.     printf(".");
  609.  
  610.       sl=i24->scan_line(y);
  611.   //initally set all the planes to clear, this should leave the paper white
  612.       memset(cp,0,500);  memset(mp,0,500);  memset(yp,0,500); memset(kp,0,500);
  613.   // now scan through the cyan plane of this scan line and pick out the bits
  614.       for (x=0,bito=7;x<im->width();x++)
  615.       {
  616.     outcv=RGB2C(sl[x*3],sl[x*3+1],sl[x*3+2]);
  617.     outyv=RGB2Y(sl[x*3],sl[x*3+1],sl[x*3+2]);
  618.     outmv=RGB2M(sl[x*3],sl[x*3+1],sl[x*3+2]);
  619.     if (outcv==outyv && outyv==outmv)
  620.     {
  621.       if ((rev && !outcv) || (!rev && outcv))
  622.         kp[x/8]^=(1<<bito);
  623.     } else
  624.     {
  625.       cp[x/8]^=(outcv<<bito);
  626.       yp[x/8]^=(outyv<<bito);
  627.       mp[x/8]^=(outmv<<bito);
  628.     }
  629.     if ((bito--)==0)
  630.       bito=7;
  631.       }
  632.       fprintf(fp,"%c*b%dV",27,w/8);  // print out the black plane first
  633.       fwrite(kp,1,w/8,fp);
  634.       fprintf(fp,"%c*b%dV",27,w/8);  // now the cyan plane
  635.       fwrite(cp,1,w/8,fp);
  636.       fprintf(fp,"%c*b%dV",27,w/8);  // now the yellow plane
  637.       fwrite(yp,1,w/8,fp);
  638.       fprintf(fp,"%c*b%dW",27,w/8);  // now the magenta plane
  639.       fwrite(mp,1,w/8,fp);
  640.     }
  641.     fprintf(fp,"%c*rbC%c",27,12);  // end graphics, switch everthing back to defaults
  642.                    // and print a form feed to eject the paper.
  643.     fclose(fp); // flush out anything in the buffers and close the file
  644.     delete i24;  // clean up the memory that we allocated to the image and the palette
  645.   }
  646.   printf("\n");
  647.   delete im;
  648.   delete pal;
  649. }
  650.  
  651. main(int argc, char **argv)
  652. {
  653.   setcbrk(1);  // set the control break on, so that printing can be interrupted
  654.   deskjet_print(argc,argv);
  655.